home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Wissenschaft & Technik / Open Prolog / External Predicates… / Sources / draw.p < prev    next >
Text File  |  1995-11-10  |  22KB  |  656 lines

  1. {$D+} { MacsBug symbols on }
  2. {$R-} { No range checking }
  3.  
  4. UNIT draw;
  5.  
  6.   INTERFACE
  7.  
  8.     USES quickdraw, toolUtils, scrap, standardFile,prlxdefinitions,
  9.          prlxLibraries;
  10.  
  11.     PROCEDURE entrypoint(plist: prlxptr);
  12.  
  13.   IMPLEMENTATION
  14.  
  15.     CONST
  16.       openCommand = 1;
  17.       closeCommand = 2;
  18.       lineCommand = 3;
  19.       rectCommand = 4;
  20.       textCommand = 5;
  21.       penSizeCommand = 6;
  22.       penModeCommand = 7;
  23.       penPatCommand = 8;
  24.       foreColorCommand = 9;
  25.       backColorCommand = 10;
  26.       eraseCommand = 11;
  27.       ovalCommand = 12;
  28.  
  29.     TYPE
  30.  (*     rectPtr = ^rect; *)
  31.       pickKind = (pickLine, pickRect,pickOval, pickText, pickPenSize, pickPenMode,
  32.                   pickPenPat, pickForeColor, pickBackColor);
  33.       pickHandle = ^pickPtr;
  34.       pickPtr = ^pickRec;
  35.       pickRec = RECORD
  36.                   sized: boolean;
  37.                   boundsRect: rect;
  38.                   next: pickHandle;
  39.                   CASE kind: pickKind OF
  40.                     pickLine:
  41.                       (lineStart, lineEnd: point);
  42.                     pickRect,pickOval:
  43.                       (r: rect);
  44.                     pickText:
  45.                       (s: stringHandle;
  46.                        p: point);
  47.                     pickPenSize:
  48.                       (width, height: integer);
  49.                     pickPenMode:
  50.                       (m: integer);
  51.                     pickPenPat:
  52.                       (patternIndex: integer);
  53.                     pickForeColor:
  54.                       (colorIndex: integer);
  55.                     pickBackColor:
  56.                       (colorIndxex: integer);
  57.                 END;
  58.       drawingRecord = RECORD
  59.                         pen: penState;
  60.                         foregroundColor, backgroundColor: longint;
  61.                       END;
  62.  
  63.       graphicWindowPtr = ^graphicWindowRec;
  64.       graphicWindowRec = RECORD
  65.                            window: windowRecord;
  66.                            occupied: boolean;
  67.                            pick, lastPick: pickHandle;
  68.                            picturePresent: boolean; {i.e. at least one visible
  69.                                                      command}
  70.                            boundsRect: rect;
  71.                            defaultState, currentState: drawingRecord;
  72.                            oldClip: rgnHandle;
  73.                          END;
  74.  
  75.     PROCEDURE main(plist: prlxptr);
  76.       FORWARD;
  77.  
  78.     PROCEDURE entrypoint(plist: prlxptr);
  79.  
  80.       BEGIN
  81.         main(plist);
  82.       END;
  83.  
  84.     FUNCTION integerMin(a, b: longint): longint;
  85.  
  86.       BEGIN
  87.         IF a > b THEN
  88.           integerMin := b
  89.         ELSE
  90.           integerMin := a;
  91.       END;
  92.  
  93.     FUNCTION integerMax(a, b: longint): longint;
  94.  
  95.       BEGIN
  96.         IF a < b THEN
  97.           integerMax := b
  98.         ELSE
  99.           integerMax := a;
  100.       END;
  101.  
  102.     PROCEDURE getDrawingState(theWindow: graphicWindowPtr;
  103.                               VAR state: drawingRecord);
  104.  
  105.       BEGIN
  106.         WITH state DO
  107.           BEGIN
  108.           getPenState(pen);
  109.           foreGroundColor := windowPtr(theWindow)^.fgColor;
  110.           backGroundColor := windowPtr(theWindow)^.bkColor;
  111.           END;
  112.       END;
  113.  
  114.     PROCEDURE setDrawingState(VAR state: drawingRecord);
  115.  
  116.       BEGIN
  117.         WITH state DO
  118.           BEGIN
  119.           setPenState(pen);
  120.           foreColor(foreGroundColor);
  121.           backColor(backGroundColor);
  122.           END;
  123.       END;
  124.  
  125.     FUNCTION qdColor(colorIndex: longint): longint;
  126.  
  127.       BEGIN
  128.         CASE colorIndex OF
  129.           0: qdColor := blackColor;
  130.           1: qdColor := yellowColor;
  131.           2: qdColor := magentaColor;
  132.           3: qdColor := redColor;
  133.           4: qdColor := cyanColor;
  134.           5: qdColor := greenColor;
  135.           6: qdColor := blueColor;
  136.           7: qdColor := whiteColor;
  137.         END;
  138.       END;
  139.  
  140.     FUNCTION drawHandler(theWindow: graphicWindowPtr;
  141.                          parameter: longint;
  142.                          message: integer): longint;
  143.  
  144.       VAR
  145.         s: str255;
  146.         oldPort: grafPtr;
  147.         scrapPic: picHandle;
  148.         rptr: rectPtr;
  149.         theRect1,theRect2: rect;
  150.         ignoreBoolean: boolean;
  151.         ignoreLongint: longint;
  152.  
  153.       PROCEDURE drawpick(theWindow: graphicWindowPtr);
  154.  
  155.         VAR
  156.           myPick: pickHandle;
  157.           pat: pattern;
  158.           theRect: rect;
  159.  
  160.         BEGIN
  161.           setDrawingState(theWindow^.defaultState);
  162.           getClip(theWindow^.oldClip);
  163.           theRect := windowPtr(theWindow)^.portRect;
  164.           theRect.bottom := theRect.bottom - 15;
  165.           theRect.right := theRect.right - 15;
  166.           clipRect(theRect);
  167.           myPick := theWindow^.pick;
  168.           WHILE myPick <> NIL DO
  169.             BEGIN
  170.             hlock(handle(myPick));
  171.             WITH myPick^^ DO
  172.               BEGIN
  173.               CASE kind OF
  174.                 pickLine:
  175.                   BEGIN
  176.                   moveTo(lineStart.h, lineStart.v);
  177.                   lineTo(lineEnd.h, lineEnd.v);
  178.                   END;
  179.                 pickRect: frameRect(r);
  180.                 pickOval: frameOval(r);
  181.                 pickText:
  182.                   BEGIN
  183.                   moveTo(p.h, p.v);
  184.                   hLock(handle(s));
  185.                   drawString(s^^);
  186.                   hUnLock(handle(s));
  187.                   END;
  188.                 pickPenSize: penSize(width, height);
  189.                 pickPenMode: penMode(m);
  190.                 pickPenPat:
  191.                   BEGIN
  192.                   getIndPattern(pat, sysPatListID, patternIndex);
  193.                   penPat(pat);
  194.                   END;
  195.                 pickForeColor: foreColor(qdColor(colorIndex));
  196.                 pickBackColor: backColor(qdColor(colorIndex));
  197.               END;
  198.               hUnlock(handle(myPick));
  199.               myPick := myPick^^.next;
  200.               END;
  201.             END;
  202.           setClip(theWindow^.oldClip);
  203.           setDrawingState(theWindow^.defaultState);
  204.         END;
  205.  
  206.       BEGIN
  207.         drawHandler := messageOK;
  208.         CASE message OF
  209.           eventActivate, eventResume:
  210.             BEGIN
  211.             getport(oldport);
  212.             setPort(windowPtr(theWindow));
  213.             drawGrowIcon(windowPtr(theWindow));
  214.             setport(oldPort);
  215.             END;
  216.           eventGetGrowLimit:
  217.             IF theWindow^.picturePresent THEN
  218.               BEGIN
  219.               rptr := rectPtr(parameter);
  220.               WITH rptr^ DO
  221.                 BEGIN
  222.                 topLeft := theWindow^.boundsRect.topLeft;
  223.                 botRight := theWindow^.boundsRect.botRight;
  224.                 bottom := bottom + 16;
  225.                 right := right + 16;
  226.                 END;
  227.               END;
  228.           eventSetWindowSize:
  229.             BEGIN
  230.             getport(oldport);
  231.             setPort(windowPtr(theWindow));
  232.             theRect1 := windowPtr(theWindow)^.portRect;
  233.             WITH theRect1 DO
  234.               BEGIN
  235.           bottom:=bottom-16;
  236.                right := right - 16;
  237.               END;
  238.           
  239.             sizeWindow(windowPtr(theWindow), loword(parameter),
  240.                        hiword(parameter), false);
  241.                
  242.             theRect2 := windowPtr(theWindow)^.portRect;
  243.             invalRect(theRect2);
  244.             WITH theRect2 DO
  245.               BEGIN
  246.               bottom := bottom -16;
  247.               right := right -16;
  248.            END;
  249.            ignoreBoolean:=sectRect(theRect1, theRect2, theRect1);
  250.             validRect(theRect1);
  251.                 setport(oldPort);
  252.             END;
  253.  
  254.           eventUpdate:
  255.             BEGIN
  256.             getport(oldport);
  257.             setPort(windowPtr(theWindow));
  258.             beginUpdate(windowPtr(theWindow));
  259.         eraseRect(windowPtr(theWindow)^.portRect);
  260.             drawGrowIcon(windowPtr(theWindow));
  261.             drawPick(theWindow);
  262.             UpdtControl(windowPtr(theWindow), windowPeek(theWindow)^.updateRgn);
  263.             endUpdate(windowPtr(theWindow));
  264.             setport(oldPort);
  265.             END;
  266.  
  267.           eventQuit: drawHandler := messageQuit;
  268.           eventMenuSelect:
  269.             BEGIN
  270.             getport(oldport);
  271.             setPort(windowPtr(theWindow));
  272.             IF (hiword(parameter) = editmenu) AND (loword(parameter) =
  273.                copyitem) THEN
  274.               BEGIN
  275.               IF theWindow^.picturePresent THEN
  276.                 clipRect(theWindow^.boundsRect)
  277.               ELSE
  278.                 clipRect(windowPtr(theWindow)^.portRect);
  279.               scrapPic := openPicture(windowPtr(theWindow)^.portRect);
  280.               drawPick(theWindow);
  281.               closePicture;
  282.               hlock(handle(scrapPic));
  283.               IF zeroScrap = noErr THEN
  284.                 IF putScrap(getHandleSize(handle(scrapPic)), 'PICT',
  285.                             handle(scrapPic)^) = noErr THEN
  286.                   IF unloadScrap = noErr THEN drawHandler := messageOK;
  287.               hUnLock(handle(scrapPic));
  288.               END
  289.             ELSE IF (hiword(parameter) = editmenu) AND (loword(parameter) =
  290.                     cutitem) THEN
  291.               BEGIN
  292.               IF theWindow^.picturePresent THEN
  293.                 frameRect(theWindow^.boundsRect);
  294.               END
  295.             ELSE
  296.               drawHandler := messageNoReply;
  297.  
  298.             setport(oldPort);
  299.             hiliteMenu(0);
  300.             END;
  301.           OTHERWISE drawHandler := messageNoReply;
  302.         END;
  303.  
  304.       END;
  305.  
  306.     PROCEDURE main;
  307.  
  308.       VAR
  309.         s: str255;
  310.         i: integer;
  311.         l, m: longint;
  312.         newPick: pickHandle;
  313.         pat: pattern;
  314.  
  315.       PROCEDURE draw;
  316.  
  317.         VAR
  318.           theRect: rect;
  319.           theWindow: graphicWindowPtr;
  320.           result: longint;
  321.           p: procPtr;
  322.           st: str255;
  323.           u, x, y, z: longint;
  324.           oldPort: grafptr;
  325.           aControl: controlHandle;
  326.           myFontInfo: fontInfo;
  327.  
  328.         PROCEDURE addPick(p: pickHandle;
  329.                           theWindow: graphicWindowPtr);
  330.  
  331.           VAR
  332.             q: pickHandle;
  333.  
  334.           BEGIN
  335.             IF theWindow^.pick = NIL THEN
  336.               theWindow^.pick := p
  337.             ELSE
  338.               theWindow^.lastPick^^.next := p;
  339.  
  340.             theWindow^.lastPick := p;
  341.             p^^.next := NIL;
  342.             IF theWindow^.picturePresent THEN
  343.               BEGIN
  344.               IF p^^.sized THEN
  345.                 unionRect(theWindow^.boundsRect, p^^.boundsRect,
  346.                           theWindow^.boundsRect);
  347.               END
  348.             ELSE
  349.               BEGIN
  350.               theWindow^.boundsRect := p^^.boundsRect;
  351.               theWindow^.picturePresent := p^^.sized;
  352.               END;
  353.           END;
  354.  
  355.         BEGIN
  356.           plist^.determinate := true;
  357.           newPick := NIL;
  358.           getPort(oldPort);
  359.           theWindow := graphicWindowPtr(plist^.data[2]);
  360.           IF theWindow^.occupied THEN
  361.             BEGIN
  362.             setPort(windowPtr(theWindow));
  363.             setDrawingState(theWindow^.currentState);
  364.             getClip(theWindow^.oldClip);
  365.             theRect := windowPtr(theWindow)^.portRect;
  366.             theRect.bottom := theRect.bottom - 15;
  367.             theRect.right := theRect.right - 15;
  368.             clipRect(theRect);
  369.  
  370.             END;
  371.  
  372.           CASE value(1, plist) OF
  373.             openCommand:
  374.               IF NOT graphicWindowPtr(plist^.data[2])^.occupied THEN
  375.                 BEGIN { new window }
  376.                 x := value(subterm(1, 2, plist), plist);
  377.                 y := value(subterm(2, 2, plist), plist);
  378.                 u := value(subterm(3, 2, plist), plist);
  379.                 z := value(subterm(4, 2, plist), plist);
  380.                 st := text(2, plist);
  381.                 setRect(theRect, y, x, z, u);
  382.                 p := @drawHandler;
  383.                 theWindow := graphicWindowPtr(newWindow(ptr(plist^.data[2]),
  384.                                                         theRect, st, false,
  385.                                                         documentProc,
  386.                                                         pointer( - 1), false,
  387.                                                         longint(p)));
  388.                 setPort(windowPtr(theWindow));
  389.                 graphicWindowPtr(theWindow)^.occupied := true;
  390.                 graphicWindowPtr(theWindow)^.pick := NIL;
  391.                 graphicWindowPtr(theWindow)^.picturePresent := false;
  392.                 setRect(theRect, z - 16, x, z - 1, u - 16);
  393.                 aControl := newControl(windowPtr(theWindow), theRect, '', true,
  394.                                        0, 0, 10, scrollBarProc, 0);
  395.                 setRect(theRect, y, u - 16, z - 16, u);
  396.                 aControl := newControl(windowPtr(theWindow), theRect, '', true,
  397.                                        0, 0, 10, scrollBarProc, 0);
  398.                 getDrawingState(theWindow, theWindow^.defaultState);
  399.                 theWindow^.oldClip := newRgn;
  400.                 getClip(theWindow^.oldClip);
  401.                 showWindow(windowPtr(theWindow));
  402.                 END;
  403.             eraseCommand:
  404.               WITH theWindow^ DO
  405.                 IF occupied THEN
  406.                   BEGIN { only if occupied }
  407.                   WHILE pick <> NIL DO
  408.                     BEGIN
  409.                     newPick := pick^^.next;
  410.                     disposHandle(handle(pick));
  411.                     pick := newPick;
  412.                     END;
  413.                   pick := NIL;
  414.                   picturePresent := false;
  415.                   setDrawingState(theWindow^.defaultState);
  416.                   theRect := windowPtr(theWindow)^.portRect;
  417.                   eraseRect(theRect);
  418.                   invalRect(theRect);
  419.                   END;
  420.             closeCommand:
  421.               WITH theWindow^ DO
  422.                 IF occupied THEN
  423.                   BEGIN { only if occupied }
  424.  
  425.                   WHILE pick <> NIL DO
  426.                     BEGIN
  427.                     newPick := pick^^.next;
  428.                     disposHandle(handle(pick));
  429.                     pick := newPick;
  430.                     END;
  431.                   occupied := false;
  432.                   pick := NIL;
  433.                   picturePresent := false;
  434.                   disposeRgn(theWindow^.oldClip);
  435.                   closeWindow(windowPtr(plist^.data[2]));
  436.                   END;
  437.             lineCommand:
  438.               IF theWindow^.occupied THEN
  439.                 BEGIN
  440.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  441.                 x := value(subterm(1, 2, plist), plist);
  442.                 y := value(subterm(2, 2, plist), plist);
  443.                 u := value(subterm(3, 2, plist), plist);
  444.                 z := value(subterm(4, 2, plist), plist);
  445.                 MoveTo(x, y);
  446.                 Lineto(u, z);
  447.                 WITH newPick^^ DO
  448.                   BEGIN
  449.                   sized := true;
  450.                   boundsRect.top := integerMin(y, z);
  451.                   boundsRect.left := integerMin(x, u);
  452.                   boundsRect.bottom := integerMax(y,
  453.                                        z) + theWindow^.currentState.pen.pnSize.
  454.                                        v;
  455.                   boundsRect.right := integerMax(x,
  456.                                       u) + theWindow^.currentState.pen.pnSize.h
  457.                                       ;
  458.                   kind := pickLine;
  459.                   lineStart.h := x;
  460.                   lineStart.v := y;
  461.                   lineEnd.h := u;
  462.                   lineEnd.v := z;
  463.                   END;
  464.                 addPick(newPick, theWindow);
  465.                 END;
  466.             textCommand:
  467.               IF theWindow^.occupied THEN
  468.                 BEGIN
  469.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  470.                 x := value(subterm(1, 2, plist), plist);
  471.                 y := value(subterm(2, 2, plist), plist);
  472.                 st := text(subterm(3, 2, plist), plist);
  473.                 MoveTo(x, y);
  474.                 DrawString(st);
  475.                 getFontInfo(myFontInfo);
  476.                 WITH newPick^^ DO
  477.                   BEGIN
  478.                   sized := true;
  479.                   boundsRect.top := y - myFontINfo.ascent;
  480.                   boundsRect.left := x;
  481.                   boundsRect.bottom := y + myFontINfo.descent;
  482.                   boundsRect.right := x + stringWidth(st);
  483.                   kind := pickText;
  484.                   p.h := x;
  485.                   p.v := y;
  486.                   s := newString(st);
  487.                   END;
  488.                 addPick(newPick, theWindow);
  489.                 END;
  490.            ovalCommand:
  491.               IF theWindow^.occupied THEN
  492.                 BEGIN
  493.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  494.                 x := value(subterm(1, 2, plist), plist);
  495.                 y := value(subterm(2, 2, plist), plist);
  496.                 u := value(subterm(3, 2, plist), plist);
  497.                 z := value(subterm(4, 2, plist), plist);
  498.                 setRect(theRect, x, y, u, z);
  499.                 frameOval(theRect);
  500.                 WITH newPick^^ DO
  501.                   BEGIN
  502.                   sized := true;
  503.                   boundsRect := theRect;
  504.                   kind := pickOval;
  505.                   r := theRect;
  506.                   END;
  507.                 addPick(newPick, theWindow);
  508.                 END;
  509.             rectCommand:
  510.               IF theWindow^.occupied THEN
  511.                 BEGIN
  512.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  513.                 x := value(subterm(1, 2, plist), plist);
  514.                 y := value(subterm(2, 2, plist), plist);
  515.                 u := value(subterm(3, 2, plist), plist);
  516.                 z := value(subterm(4, 2, plist), plist);
  517.                 setRect(theRect, x, y, u, z);
  518.                 frameRect(theRect);
  519.                 WITH newPick^^ DO
  520.                   BEGIN
  521.                   sized := true;
  522.                   boundsRect := theRect;
  523.                   kind := pickRect;
  524.                   r := theRect;
  525.                   END;
  526.                 addPick(newPick, theWindow);
  527.                 END;
  528.             penSizeCommand:
  529.               IF theWindow^.occupied THEN
  530.                 BEGIN
  531.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  532.                 x := value(subterm(1, 2, plist), plist);
  533.                 y := value(subterm(2, 2, plist), plist);
  534.                 penSize(x, y);
  535.                 WITH newPick^^ DO
  536.                   BEGIN
  537.                   sized := false;
  538.                   kind := pickPenSize;
  539.                   width := x;
  540.                   height := y;
  541.                   END;
  542.                 addPick(newPick, theWindow);
  543.                 END;
  544.             penModeCommand:
  545.               IF theWindow^.occupied THEN
  546.                 BEGIN
  547.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  548.                 x := value(subterm(1, 2, plist), plist);
  549.                 penMode(x);
  550.                 WITH newPick^^ DO
  551.                   BEGIN
  552.                   sized := false;
  553.                   kind := pickPenMode;
  554.                   m := x;
  555.                   END;
  556.                 addPick(newPick, theWindow);
  557.                 END;
  558.             penPatCommand:
  559.               IF theWindow^.occupied THEN
  560.                 BEGIN
  561.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  562.                 x := value(subterm(1, 2, plist), plist);
  563.                 getIndPattern(pat, sysPatListID, x);
  564.                 penPat(pat);
  565.                 WITH newPick^^ DO
  566.                   BEGIN
  567.                   sized := false;
  568.                   kind := pickPenPat;
  569.                   patternIndex := x;
  570.                   END;
  571.                 addPick(newPick, theWindow);
  572.                 END;
  573.             foreColorCommand:
  574.               IF theWindow^.occupied THEN
  575.                 BEGIN
  576.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  577.                 x := value(subterm(1, 2, plist), plist);
  578.                 foreColor(qdColor(x));
  579.                 WITH newPick^^ DO
  580.                   BEGIN
  581.                   sized := false;
  582.                   kind := pickForeColor;
  583.                   colorIndex := x;
  584.                   END;
  585.                 addPick(newPick, theWindow);
  586.                 END;
  587.             backColorCommand:
  588.               IF theWindow^.occupied THEN
  589.                 BEGIN
  590.                 newPick := pickHandle(newHandle(sizeOf(pickRec)));
  591.                 x := value(subterm(1, 2, plist), plist);
  592.                 backColor(qdColor(x));
  593.                 WITH newPick^^ DO
  594.                   BEGIN
  595.                   sized := false;
  596.                   kind := pickBackColor;
  597.                   colorIndex := x;
  598.                   END;
  599.                 addPick(newPick, theWindow);
  600.                 END;
  601.  
  602.           END; { case }
  603.           IF theWindow^.occupied THEN
  604.             BEGIN
  605.             getDrawingState(theWindow, theWindow^.currentState);
  606.             setDrawingState(theWindow^.defaultState);
  607.             setClip(theWindow^.oldClip);
  608.             END;
  609.           IF oldPort <> grafPtr(theWindow) THEN setPort(oldPort);
  610.         END; { procedure }
  611.  
  612.       BEGIN
  613.         WITH plist^ DO
  614.           BEGIN
  615.           CASE request OF
  616.             getPRLXInfo: 
  617.                         begin
  618.                         data[1] := 1; {number of predicates defined}
  619.                         data[2]:=eventsVersion;
  620.                         end;
  621.             initialisepredicate:
  622.               CASE id OF
  623.                 1: {draw/3}
  624.                   BEGIN
  625.                   s := 'draw'; {name}
  626.                   data[1] := 3; {arity - command,argument,result}
  627.                   data[2] := longint(newPtr(sizeOf(graphicWindowRec))); {permanent
  628.                     data}
  629.                   graphicWindowPtr(data[2])^.occupied := false;
  630.                   END;
  631.                 OTHERWISE
  632.                   errorstr('predicate index out of range at initialise', plist);
  633.               END;
  634.             callpredicate:
  635.               BEGIN
  636.               successful := true;
  637.               CASE id OF
  638.                 1: draw;
  639.                 OTHERWISE
  640.                   errorstr('predicate index out of range at call', plist);
  641.               END;
  642.               END;
  643.             closepredicate:
  644.               BEGIN
  645.               CASE id OF
  646.                 1: {draw} ;
  647.                 OTHERWISE
  648.                   errorstr('predicate index out of range at close', plist);
  649.               END;
  650.               END;
  651.             OTHERWISE errorstr('unknown call to external procedures', plist);
  652.           END;
  653.           END;
  654.       END;
  655. END.
  656.